{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "from common import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "RESULT_JSON = \"/Users/law/repos/viper/results/breakdown/breakdown_revision.json\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from collections import defaultdict\n",
    "runs = defaultdict(list)\n",
    "\n",
    "BMS = get_all_runs(RESULT_JSON)\n",
    "\n",
    "# pprint(BMS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)\n",
    "\n",
    "TIMERS = (\"lock\", \"pmem\", \"map\")\n",
    "\n",
    "def get_sum_time(bm, op_type):\n",
    "    total_ns = 0\n",
    "    for timer in TIMERS:\n",
    "        total_ns += bm[f\"{op_type}-{timer}\"]\n",
    "    return total_ns\n",
    "\n",
    "st_bm = BMS[0]\n",
    "at_bm = BMS[1]\n",
    "\n",
    "st_insert = get_sum_time(BMS[0], \"insert\")\n",
    "st_get = get_sum_time(BMS[0], \"get\")\n",
    "st_update = get_sum_time(BMS[0], \"update\")\n",
    "st_delete = get_sum_time(BMS[0], \"delete\")\n",
    "\n",
    "at_insert = get_sum_time(BMS[1], \"insert\")\n",
    "at_get = get_sum_time(BMS[1], \"get\")\n",
    "at_update = get_sum_time(BMS[1], \"update\")\n",
    "at_delete = get_sum_time(BMS[1], \"delete\")\n",
    "\n",
    "bar_width = 0.7\n",
    "st_pos = np.arange(4)\n",
    "al_pos = [x + bar_width for x in st_pos]\n",
    "POS = [st_pos, al_pos]\n",
    "\n",
    "# multi thread op time in us\n",
    "insert_op_time = 2.35\n",
    "get_op_time    = 1.11\n",
    "update_op_time = 2.61\n",
    "delete_op_time = 2.83\n",
    "\n",
    "\n",
    "fig, ax = plt.subplots(1, 1, figsize=(2.5, 2.5))\n",
    "\n",
    "STYLES = {\n",
    "    'pmem': (PMEM_COLOR, ''),\n",
    "    'map' : (DRAM_COLOR, ''),\n",
    "    'lock': (\"#990000\",  ''),\n",
    "    'val' : (\"#009900\",  ''),\n",
    "}\n",
    "\n",
    "text_y = 1.05\n",
    "dur_fs = 18\n",
    "text_rot = 40\n",
    "\n",
    "# ALL_RUNS = [(st_bm, st_insert, st_get, st_update, st_delete)] \n",
    "ALL_RUNS = [(at_bm, at_insert, at_get, at_update, at_delete)]\n",
    "for i, (bm, insert, get, update, delete) in enumerate(ALL_RUNS):\n",
    "    # INSERT\n",
    "    insert_lock = bm[\"insert-lock\"] / insert\n",
    "    insert_write = bm[\"insert-pmem\"] / insert\n",
    "    insert_update = bm[\"insert-map\"] / insert\n",
    "    ax.bar(POS[i][0], insert_lock, bar_width, bottom=0, \n",
    "           label=\"Fetch/\\nLock\", color=STYLES['lock'][0], hatch=STYLES['lock'][1])\n",
    "    ax.bar(POS[i][0], insert_update, bar_width, bottom=insert_lock, \n",
    "           label=\"Map\", color=STYLES['map'][0], hatch=STYLES['map'][1])\n",
    "    ax.bar(POS[i][0], insert_write, bar_width, bottom=insert_lock + insert_update, \n",
    "           label=\"PMem\", color=STYLES['pmem'][0], hatch=STYLES['pmem'][1])\n",
    "    ax.text(POS[i][0], text_y, f\"{insert_op_time}\", ha='center', fontsize=dur_fs, rotation=text_rot)\n",
    "        \n",
    "    # GET\n",
    "    get_map = bm[\"get-map\"] / get\n",
    "    get_lock = bm[\"get-lock\"] / get\n",
    "    get_read = bm[\"get-pmem\"] / get\n",
    "    ax.bar(POS[i][1], get_lock, bar_width, bottom=0, \n",
    "           color=STYLES['lock'][0], hatch=STYLES['lock'][1])\n",
    "    ax.bar(POS[i][1], get_map, bar_width, bottom=get_lock, \n",
    "           color=STYLES['map'][0], hatch=STYLES['map'][1])\n",
    "    ax.bar(POS[i][1], get_read, bar_width, bottom=get_map + get_lock,\n",
    "           color=STYLES['pmem'][0], hatch=STYLES['pmem'][1])\n",
    "    ax.text(POS[i][1], text_y, f\"{get_op_time}\", ha='center', fontsize=dur_fs, rotation=text_rot)\n",
    "    \n",
    "    # UPDATE\n",
    "    update_map = bm[\"update-map\"] / update\n",
    "    update_lock = bm[\"update-lock\"] / update\n",
    "    update_modify = bm[\"update-pmem\"] / update\n",
    "    ax.bar(POS[i][2], update_lock, bar_width, bottom=0, \n",
    "           color=STYLES['lock'][0], hatch=STYLES['lock'][1])\n",
    "    ax.bar(POS[i][2], update_map, bar_width, bottom=update_lock, \n",
    "           color=STYLES['map'][0], hatch=STYLES['map'][1])\n",
    "    ax.bar(POS[i][2], update_modify, bar_width, bottom=update_map + update_lock,\n",
    "           color=STYLES['pmem'][0], hatch=STYLES['pmem'][1])\n",
    "    ax.text(POS[i][2], text_y, f\"{update_op_time}\", ha='center', fontsize=dur_fs, rotation=text_rot)\n",
    "\n",
    "        \n",
    "    # DELETE\n",
    "    delete_lock = bm[\"delete-lock\"] / delete\n",
    "    delete_write = bm[\"delete-pmem\"] / delete\n",
    "    delete_update = bm[\"delete-map\"] / delete\n",
    "    ax.bar(POS[i][3], delete_lock, bar_width, bottom=0, \n",
    "           color=STYLES['lock'][0], hatch=STYLES['lock'][1])\n",
    "    ax.bar(POS[i][3], delete_update, bar_width, bottom=delete_lock, \n",
    "           color=STYLES['map'][0], hatch=STYLES['map'][1])\n",
    "    ax.bar(POS[i][3], delete_write, bar_width, bottom=delete_lock + delete_update,\n",
    "           color=STYLES['pmem'][0], hatch=STYLES['pmem'][1])\n",
    "    ax.text(POS[i][3], text_y, f\"{delete_op_time}\", ha='center', fontsize=dur_fs, rotation=text_rot)\n",
    "    \n",
    "\n",
    "ax.set_xticks([r + (0.0 * bar_width) for r in st_pos])\n",
    "ax.xaxis.set_tick_params(pad=1)\n",
    "ax.set_xticklabels([\"PUT\", \"GET\", \"UPDATE\", \"DELETE\"], fontsize=18, rotation=30)\n",
    "\n",
    "ax.set_yticks([0, 0.2, 0.4, 0.6, 0.8, 1])\n",
    "# ax.set_yticklabels([\"\", 0.2, \"\", 0.6, \"\", 1])\n",
    "\n",
    "ax.set_ylabel(\"Normalized dur./op\", fontsize=20)\n",
    "ax.yaxis.set_label_coords(-0.28, 0.45)\n",
    "\n",
    "ax.text(5, 0.9, \"←avg. dur.\\nin $µs$\", ha='center', fontsize=dur_fs + 2)\n",
    "\n",
    "# Put a legend below current axis\n",
    "handles, labels = ax.get_legend_handles_labels()\n",
    "ax.legend(handles[::-1], labels[::-1], loc='center right', bbox_to_anchor=(1.74, 0.4), \n",
    "          ncol=1, frameon=False, framealpha=1,\n",
    "          fontsize=18, columnspacing=0.3, handletextpad=0.2, labelspacing=0.3,\n",
    "          handlelength=1.8, borderpad=0.1)\n",
    "\n",
    "for tick in ax.yaxis.get_major_ticks():\n",
    "    tick.label.set_fontsize(18)\n",
    "\n",
    "plt.tick_params(axis='x', bottom=False)\n",
    "ax.set_axisbelow(True)\n",
    "ax.grid(axis='y', which='major')\n",
    "hide_border(ax)\n",
    "\n",
    "fig.savefig('charts/breakdown_half.pdf', bbox_inches='tight')\n",
    "fig.savefig('charts/breakdown_half.svg', bbox_inches='tight')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
